#ifndef key_generator_hpp
#define key_generator_hpp

#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

#include <cryptopp/secblock.h>
#include <cryptopp/osrng.h>
#include <cryptopp/randpool.h>
#include <cryptopp/cryptlib.h>

#include "components/defs/util_types.hpp"

namespace components
{
namespace encrypt
{
class key_generator: public boost::enable_shared_from_this<key_generator>, private boost::noncopyable
{
private:
    boost::asio::io_service ios_;
    //maybe static because it will return the same all calling threads otherwise
    CryptoPP::AutoSeededRandomPool RandPool;
    boost::asio::strand  strand_;
    std::string name_;
    key_generator();
    template<typename Handler>
    void generate(std::size_t ksize,crypto_buf_t& output,Handler handler)
    {
        try
        {
            RandPool.GenerateBlock(output,ksize);
            handler(CryptoPP::Exception(CryptoPP::Exception::NOT_IMPLEMENTED,std::string("Success")));
        }
        catch(CryptoPP::Exception const &e )
        {
            handler(e);
        }
    }
public:
    key_generator(boost::asio::io_service& ios):ios_(ios),strand_(ios)
    {
        name_=std::string(__FUNCTION__);
    }

    template<typename Handler>
    bool exec(std::size_t key_size,crypto_buf_t& output,Handler handler)
    {
        try
        {
            ios_.post(
                strand_.wrap(
                    boost::protect(
                        boost::bind(&key_generator::generate,
                                    shared_from_this(),
                                    key_size,boost::ref(output),handler)
                    )
                )
            );
            return true
        }
        catch(std::exception& e)
        {
            return false;
        }
    }
};


} // end namespace encrypt
} // end namespace components

#endif //define double include key_generator_hpp
